package cn.vehicle.convert;

import cn.vehicle.domains.info.*;
import cn.vehicle.domains.vo.req.zs.*;
import cn.vehicle.domains.vo.res.zs.AlarmInfoPlate;
import cn.vehicle.domains.vo.res.zs.AlarmInfoPlateRes;
import org.springframework.stereotype.Component;

/**
 * 中视相机 HTTP 数据转换器
 * <p>
 * 用于解析中视相机上传的 HTTP 请求数据并转换为系统内部统一的数据结构。
 * 支持车牌识别、心跳、抓拍、IO 输入等多种类型的请求解析。
 * </p>
 *
 * <p>主要职责：</p>
 * <ul>
 *   <li>将中视相机接口请求对象转换为内部业务对象；</li>
 *   <li>统一不同接口的字段结构，方便系统后续处理；</li>
 *   <li>根据不同请求类型构建相应的响应数据结构。</li>
 * </ul>
 */
@Component
public class ZsHttpConvert {
    /**
     * 解析中视相机车牌识别请求
     * <p>
     * 将中视相机上传的识别请求对象 {@link ZsPlateDetectedReq} 转换为系统内部对象 {@link PlateDetectedInternalInfo}。
     * </p>
     *
     * @param req 中视相机上传的车牌识别请求
     * @return 封装后的系统内部识别信息对象
     */
    public PlateDetectedInternalInfo parseZsPlateDetectedReq(ZsPlateDetectedReq req) {
        // 创建内部车牌识别信息对象
        PlateDetectedInternalInfo plateDetectedInternalInfo = new PlateDetectedInternalInfo();

        InternalVehicleInfo internalVehicleInfo = new InternalVehicleInfo();
        // 从请求中提取车牌识别结果数据
        AlarmInfoPlateReq.PlateResult plateResult = req.getAlarmInfoPlateReq().getResult().getPlateResult();
        // 设置车牌号与图片信息
        internalVehicleInfo.setVehicleNumber(plateResult.getLicense());
        internalVehicleInfo.setPlateImgBase64(plateResult.getImageFragmentFile());
        internalVehicleInfo.setVehicleImgBase64(plateResult.getImageFile());

        // 组装相机信息（IP 与通道）
        InternalCameraInfo internalCameraInfo = new InternalCameraInfo();
        internalCameraInfo.setIp(req.getAlarmInfoPlateReq().getIpAddr());
        internalCameraInfo.setChannel(req.getAlarmInfoPlateReq().getChannel());

        plateDetectedInternalInfo.setInternalVehicleInfo(internalVehicleInfo);
        plateDetectedInternalInfo.setInternalCameraInfo(internalCameraInfo);

        // 返回封装后的内部识别信息对象
        return plateDetectedInternalInfo;
    }

    /**
     * 解析中视相机心跳请求
     *
     * @param req 中视相机上传的心跳请求
     * @return 系统内部心跳信息对象
     */
    public HeartBeatInternalInfo parseZsHeartBeatReq(ZsHeartBeatReq req) {
        // 创建心跳信息对象并填充相机 IP
        HeartBeatInternalInfo heartBeatInternalInfo = new HeartBeatInternalInfo();
        heartBeatInternalInfo.setIp(req.getIpaddr());
        return heartBeatInternalInfo;
    }

    /**
     * 构建车牌识别响应结果
     * <p>
     * 根据识别结果构建返回给中视相机的响应对象。
     * </p>
     *
     * @param result 是否识别成功
     * @param snap 是否需要触发抓拍
     * @return 返回中视协议格式的响应对象
     */
    public AlarmInfoPlateRes parseAlarmInfoPlate(Boolean result, Boolean snap) {
        // 创建响应结果对象
        AlarmInfoPlateRes alarmInfoPlateRes = new AlarmInfoPlateRes();

        AlarmInfoPlate alarmInfoPlate = new AlarmInfoPlate();
        alarmInfoPlate.setInfo(result ? "ok" : "no");

        // 若需要抓拍，则添加抓拍图片的相对路径
        if (snap) {
            AlarmInfoPlate.TriggerImage triggerImage = new AlarmInfoPlate.TriggerImage();
            triggerImage.setSnapImageRelativeUrl("/api/zs-camera/snapshot");
            alarmInfoPlate.setTriggerImage(triggerImage);
        }

        alarmInfoPlateRes.setAlarmInfoPlate(alarmInfoPlate);
        return alarmInfoPlateRes;


    }

    /**
     * 解析中视相机抓拍上报请求
     *
     * @param req 中视相机上传的抓拍请求对象
     * @return 系统内部抓拍信息对象
     */
    public SnapshotInternalInfo parseZsSnapshotInReq(ZsSnapshotInReq req) {
        SnapshotInternalInfo snapshotInternalInfo = new SnapshotInternalInfo();
        // 获取图片 Base64 数据与相机 IP
        snapshotInternalInfo.setImageFile(req.getTriggerImage().getImageFile());
        snapshotInternalInfo.setIp(req.getIpaddr());
        return snapshotInternalInfo;
    }

    /**
     * 解析中视相机 GIO 输入触发请求
     * <p>
     * 将中视上报的 GPIO 信号触发信息转换为内部通用结构。
     * </p>
     *
     * @param req 中视上传的 GPIO 输入请求
     * @return 系统内部 GIO 输入信息对象
     */
    public GIoInInternalInfo parseZsGIoInReq(ZsGIoInReq req) {
        GIoInInternalInfo gIoInInternalInfo = new GIoInInternalInfo();
        // 提取 IP 地址
        gIoInInternalInfo.setIp(req.getAlarmGIoIn().getIpaddr());
        // 设置触发信号来源与状态值
        gIoInInternalInfo.setSource(req.getAlarmGIoIn().getResult().getTriggerResult().getSource());
        gIoInInternalInfo.setValue(req.getAlarmGIoIn().getResult().getTriggerResult().getValue());
        return gIoInInternalInfo;
    }
}
